/*************************************************************************
    > File Name: face_container.h
    > Author: fanzhihui
    > Mail: 953106194@qq.com 
    > Created Time: Fri 14 Jun 2019 05:45:23 PM CST
 ************************************************************************/
#ifndef __FHTTPD_FACE_CONTAINER_H__
#define __FHTTPD_FACE_CONTAINER_H__
#include<iostream>
#include <vector>
#include <map>
#include <string>
#include <memory>
#include <mutex>
#include <exception>
#include <set>
#include "face_info.h"
#include "face_serialize.h"
#include "async_task_pool.h"

using namespace std;


struct kown_face_node_
{
	kown_face_info_t info;
	shared_ptr<kown_face_node_> next;
	shared_ptr<kown_face_node_> pre;
};
typedef struct kown_face_node_ kown_face_node_t;

class KownFaceList
{
public:
	KownFaceList()
	{	
	}
	~KownFaceList()
	{
		clear();
	}

	bool add(const std::string& key,const kown_face_info_t& in);
	bool find(const std::string& key,kown_face_info_t& out);
	bool remove(const std::string& key,kown_face_info_t& del);
	bool update(const std::string& key, const kown_face_info_t& in);

	void clear();
	void allFace(std::vector<kown_face_info_t>& all);

	inline uint32_t size(){
		return mapKownFace.size();
	}

	void reset(){
		cur = head;
	}
	bool next(kown_face_info_t& face){
		if(cur == tail){
			return false;
		}
		face = cur->info;
		cur = cur->next;
	}
private:
	shared_ptr<kown_face_node_> head;
	shared_ptr<kown_face_node_> tail;
	std::map<std::string,/*key*/ shared_ptr<kown_face_node_> > mapKownFace;
	
	shared_ptr<kown_face_node_> cur;
};


class FaceContainerException : public std::exception
{
public:
	FaceContainerException(const std::string& message):
		msg(message)
	{
	}

	const char* what() const noexcept override {
		return msg.c_str();
	}
private:

	std::string msg;
};


class FaceContainer
{
public:
	static FaceContainer* getInstance() {
		//if(!instance) {
		//	instance = new FaceContainer();
		//}

		static FaceContainer instance;
		return &instance;
	}

	void Init(shared_ptr<FaceSerializeIf> serialize);

	std::string Key(const std::string& face_id,const std::string& face_key);
	//void AddFace(uint64_t id, const std::string& image,bool overrid);
	void AddFace(const std::string& id, const std::string& key, const std::string& image,bool overrid);

	void RemoveFace(const std::string& id);
	//void ReplaceFace(uint64_t id,const std::vector<float> fs);

	//匹配人脸，返回score
	void FindFace(const std::string& image, string& face_id,string& face_key,float& score);

	void ClearFace();
private:
	FaceContainer();
	FaceContainer(const FaceContainer&);
	FaceContainer& operator=(const FaceContainer&);
	//static FaceContainer* instance;

	shared_ptr<FaceSerializeIf> faceSerial;
	map<string,/*face id*/std::set<string> /*keys*/ > id2Keys;
	KownFaceList kownFaces;
	std::mutex locker;


	ThreadPool* threadPool;
};

#endif

